package com.qianfeng.nio;

//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O/ = /O  
//                        ____/`---'/____  
//                      .   ' //| |// `.  
//                       / //||| : |||// /  
//                     / _||||| -:- |||||- /  
//                       | | /// - /// | |  
//                     | /_| ''/---/'' | |  
//                      / .-/__ `-` ___/-. /  
//                   ___`. .' /--.--/ `. . __  
//                ."" '< `.___/_<|>_/___.' >'"".  
//               | | : `- /`.;`/ _ /`;.`/ - ` : | |  
//                 / / `-. /_ __/ /__ _/ .-` / /  
//         ======`-.____`-.___/_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼                  BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  
//  


import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Set;

/**
 * Created by Jackiechan on 2022/7/4 11:00
 *
 * @author Jackiechan
 * @version 1.0
 * @since 1.0
 */
public class Nio10 {
    public static void main(String[] args) throws Exception {
        //搞一个selector
        Selector selector = Selector.open();
        //搞一个可以被选择的selectedablechannel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //绑定端口
        serverSocketChannel.bind(new InetSocketAddress("10.9.48.191", 12345));
        //设置为非阻塞
        serverSocketChannel.configureBlocking(false);
        //注册,并且对有人向我们发送连接的请求
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.err.println("服务器启动起来,并且运行在12345端口");
        //看看有没有自己感兴趣的事情发生,一旦发生后会被放到selectkeys
        while (true) {
            //首先我们要看看有没有事情发生,因为没有事情发生的话,没有必要继续做,因为是阻塞的方法,所以有返回值的时候其实就代表有正常结果了,没有正常结果会一直阻塞,一直阻塞也就没有返回值
            int select = selector.select();
            //说明发生了我们感兴趣的事情
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            //遍历
            selectionKeys.forEach(selectionKey -> {
                //如果当前发生的是请求建立连接的事件
                if (selectionKey.isAcceptable()) {
                    //如果想要和客户端建立连接那就搞连接
                    //当前是哪个通道来的连接
                    ServerSocketChannel serverSocketChannel1 = (ServerSocketChannel) selectionKey.channel();

                    try {
                        //接受连接请求,一旦接受,连接就会建立完成
                        SocketChannel socketChannel = serverSocketChannel1.accept();
                        //设置为非阻塞
                        socketChannel.configureBlocking(false);
                        System.err.println("有客户端和我们建立连接了");
                        //我们可以添加一个新的感兴趣的事情,接收数据,这次的通道是已经建立成功的通道
                        socketChannel.register(selector, SelectionKey.OP_READ);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                } else if (selectionKey.isReadable()) {
                    //有数据传递过来,可以读取数据了
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    while (true) {

                        try {
                            byteBuffer.clear();
                            //将数据不断写入到buffer
                            int read = socketChannel.read(byteBuffer);
                            //因为这个连接是不会关闭的,只是没有发送内容而已,所以永远不会到达结尾,就不会出现-1
                            if (read <=0) {
                                System.err.println("没有数据了");
                                break;
                            }
                            //翻转
                            byteBuffer.flip();
                            //读取里面的数据,假设不到1024
                            String msg = String.valueOf(Charset.forName("gbk").decode(byteBuffer));
                            System.err.println("收到的数据是:===>" + msg);
                            //我们可以选择回复数据
                            byteBuffer.rewind();
                            socketChannel.write(byteBuffer);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }

                }

            });
            //清理掉已经发生的事情,等待下次事情发生
            selectionKeys.clear();
        }

    }

}
